/**
 * 
 */
package multimedia.model.coding;

import java.util.Scanner;

import com.google.common.collect.HashBiMap;

/**
 * @author trigueros
 *
 */
public class LZW
{
    public static final int LZW = 3;
    private String inputSignal;
    private HashBiMap<String, Integer> dictionary;
    private int lastIndex;
    
    public LZW( String inputString )
    {
        inputSignal = inputString;
        dictionary = HashBiMap.create();
        
        // Create initial dictionary
        for( int i = 0; i < 10 ; i++ )
            dictionary.put(Integer.toString(i), i);
        
        dictionary.put(" ", 10);
        dictionary.put(".", 11);
        dictionary.put("-", 12);
        
        lastIndex = 13;
    }
    
    public LZW()
    {
        this(null);
    }
    
    public String encode()
    {
        StringBuilder encodedOutput = new StringBuilder();
        
        String s = inputSignal.charAt(0) + "";
        // Encode the signal 
        for( int i = 1; i < inputSignal.length(); i++ )
        {
            String c = inputSignal.charAt(i) + "";
            
            if( dictionary.containsKey( s + c ) )
            {
                s += c;
                // There was something else that needed to be done here.
            }
            else
            {
                // Writing the encoding 
                encodedOutput.append( dictionary.get(s) );
                encodedOutput.append(' '); // TODO: The spaces might cause a problem when decoding
                
                // Insert a String,Code into the Hash
                dictionary.put(s+c, lastIndex++);
                s = c;
            }
        }
        encodedOutput.append( dictionary.get(s) );
        
        return encodedOutput.toString();
    }
    
    public String decode( String encodedInput )
    {
        StringBuilder decodedOutput = new StringBuilder();
        
        Scanner iterableInput = new Scanner(encodedInput);
        
        String s = null;
        
        while( iterableInput.hasNext() )
        {
            // Since in the encoding I put the spaces in there too, I have to remove them, but there was no way to encode em properly.
//            String k = (( encodedInput.charAt(i) == ' ' ) ? encodedInput.charAt(++i) : encodedInput.charAt(i) ) + "" ;
            int k = iterableInput.nextInt();
            
            String entry = dictionary.inverse().get( new Integer(k) );
            
            if( entry == null )
            {
                entry = s + s.charAt(0);
            }
            
            decodedOutput.append(entry);
            
            if( s != null )
            {
                dictionary.put(s + entry.charAt(0), lastIndex++);
            }
            
            s = entry;            
        }
        
        return decodedOutput.toString();
    }
}


















